
package mq

import (
	"context"
	"fmt"
	"log"
	"smartposts/internal/config"
	"time"

	amqp "github.com/rabbitmq/amqp091-go"
)

// RabbitMQService holds the connection and channel
type RabbitMQService struct {
	Conn    *amqp.Connection
	Channel *amqp.Channel
}

var MQ *RabbitMQService

// InitMQ initializes the RabbitMQ service
func InitMQ() {
	cfg := config.AppConfig.RabbitMQ
	dsn := fmt.Sprintf("amqp://%s:%s@%s:%d/", cfg.User, cfg.Password, cfg.Host, cfg.Port)

	conn, err := amqp.Dial(dsn)
	if err != nil {
		log.Fatalf("Failed to connect to RabbitMQ: %s", err)
	}

	ch, err := conn.Channel()
	if err != nil {
		log.Fatalf("Failed to open a channel: %s", err)
	}

	MQ = &RabbitMQService{
		Conn:    conn,
		Channel: ch,
	}

	log.Println("Successfully connected to RabbitMQ")
}

// Publish sends a message to a specific queue
func (s *RabbitMQService) Publish(queueName string, body []byte) error {
	q, err := s.Channel.QueueDeclare(
		queueName, // name
		true,      // durable
		false,     // delete when unused
		false,     // exclusive
		false,     // no-wait
		nil,       // arguments
	)
	if err != nil {
		return fmt.Errorf("failed to declare a queue: %w", err)
	}

	ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
	defer cancel()

	err = s.Channel.PublishWithContext(ctx,
		"",     // exchange
		q.Name, // routing key
		false,  // mandatory
		false,  // immediate
		amqp.Publishing{
			ContentType: "application/json",
			Body:        body,
		})
	if err != nil {
		return fmt.Errorf("failed to publish a message: %w", err)
	}

	return nil
}

// Close closes the channel and connection
func (s *RabbitMQService) Close() {
	if s.Channel != nil {
		s.Channel.Close()
	}
	if s.Conn != nil {
		s.Conn.Close()
	}
}
